/*
 * Copyright 2024 LinQingYing. and contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of this source code is governed by the Apache License 2.0,
 * which allows users to freely use, modify, and distribute the code,
 * provided they adhere to the terms of the license.
 *
 * The software is provided "as-is", and the authors are not responsible for
 * any damages or issues arising from its use.
 *
 */

package com.linqingying.cangjie.resolve;

import com.linqingying.cangjie.descriptors.*;
import com.linqingying.cangjie.descriptors.impl.FunctionDescriptorImpl;
import com.linqingying.cangjie.descriptors.impl.PropertyAccessorDescriptor;
import com.linqingying.cangjie.descriptors.impl.PropertyAccessorDescriptorImpl;
import com.linqingying.cangjie.descriptors.impl.PropertyDescriptorImpl;
import com.linqingying.cangjie.diagnostics.rendering.CangJieDiagnosisBundle;
import com.linqingying.cangjie.name.Name;
import com.linqingying.cangjie.resolve.calls.tower.EnumClassCallableDescriptor;
import com.linqingying.cangjie.types.*;
import com.linqingying.cangjie.types.checker.CangJieTypeChecker;
import com.linqingying.cangjie.types.checker.CangJieTypePreparator;
import com.linqingying.cangjie.types.checker.CangJieTypeRefiner;
import com.linqingying.cangjie.utils.SmartSet;
import kotlin.Pair;
import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.functions.Function2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

import static com.linqingying.cangjie.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.*;

public class OverridingUtil {


    public static final OverridingUtil DEFAULT;
    private static final List<ExternalOverridabilityCondition> EXTERNAL_CONDITIONS =
            CollectionsKt.toList(ServiceLoader.load(
                    ExternalOverridabilityCondition.class,
                    ExternalOverridabilityCondition.class.getClassLoader()
            ));
    private static final CangJieTypeChecker.TypeConstructorEquality DEFAULT_TYPE_CONSTRUCTOR_EQUALITY =
            Object::equals;

    static {
        DEFAULT = new OverridingUtil(
                DEFAULT_TYPE_CONSTRUCTOR_EQUALITY, CangJieTypeRefiner.Default.INSTANCE, CangJieTypePreparator.Default.INSTANCE,
                null
        );
    }

    private final CangJieTypeRefiner cangjieTypeRefiner;
    private final CangJieTypePreparator cangjieTypePreparator;
    private final CangJieTypeChecker.TypeConstructorEquality equalityAxioms;
    private final Function2<CangJieType, CangJieType, Boolean> customSubtype;

    private OverridingUtil(
            @NotNull CangJieTypeChecker.TypeConstructorEquality axioms,
            @NotNull CangJieTypeRefiner cangjieTypeRefiner,
            @NotNull CangJieTypePreparator cangjieTypePreparator,
            @Nullable Function2<CangJieType, CangJieType, Boolean> customSubtype
    ) {
        equalityAxioms = axioms;
        this.cangjieTypeRefiner = cangjieTypeRefiner;
        this.cangjieTypePreparator = cangjieTypePreparator;
        this.customSubtype = customSubtype;
    }

    public static boolean isVisibleForOverride(
            @NotNull MemberDescriptor overriding,
            @NotNull MemberDescriptor fromSuper,
            boolean useSpecialRulesForPrivateSealedConstructors
    ) {
        return !DescriptorVisibilities.isPrivate(fromSuper.getVisibility()) &&
                DescriptorVisibilities.isVisibleIgnoringReceiver(fromSuper, overriding, useSpecialRulesForPrivateSealedConstructors);
    }

    @NotNull
    public static OverridingUtil create(
            @NotNull CangJieTypeRefiner cangjieTypeRefiner,
            @NotNull CangJieTypeChecker.TypeConstructorEquality equalityAxioms
    ) {
        return new OverridingUtil(equalityAxioms, cangjieTypeRefiner, CangJieTypePreparator.Default.INSTANCE, null);
    }

    private static boolean allHasSameContainingDeclaration(@NotNull Collection<CallableMemberDescriptor> notOverridden) {
        if (2 > notOverridden.size()) return true;

        DeclarationDescriptor containingDeclaration = notOverridden.iterator().next().getContainingDeclaration();
        return CollectionsKt.all(notOverridden, descriptor -> descriptor.getContainingDeclaration() == containingDeclaration);
    }

    @NotNull
    public static OverridingUtil createWithTypeRefiner(@NotNull CangJieTypeRefiner cangjieTypeRefiner) {
        return new OverridingUtil(DEFAULT_TYPE_CONSTRUCTOR_EQUALITY, cangjieTypeRefiner, CangJieTypePreparator.Default.INSTANCE, null);
    }

    /**
     * 创建并绑定未被覆盖的可调用成员的假覆盖。
     * 此方法用于处理未被覆盖的成员描述符的假覆盖创建，允许它们在当前类描述符中正确匹配。
     *
     * @param current       当前类描述符
     * @param notOverridden 未被覆盖的可调用成员描述符集合
     * @param strategy      覆盖策略
     */
    private static void createAndBindFakeOverrides(
            @NotNull ClassDescriptor current,
            @NotNull Collection<CallableMemberDescriptor> notOverridden,
            @NotNull OverridingStrategy strategy
    ) {
        // 优化：如果所有未被覆盖的描述符具有相同的包含声明，
        // 则可以直接为它们创建假覆盖，因为它们在其包含声明中应该能够正确匹配
        if (allHasSameContainingDeclaration(notOverridden)) {
            for (CallableMemberDescriptor descriptor : notOverridden) {
                createAndBindFakeOverride(Collections.singleton(descriptor), current, strategy);
            }
            return;
        }

        // 使用队列处理未被覆盖的成员描述符
        Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<>(notOverridden);
        while (!fromSuperQueue.isEmpty()) {
            // 查找具有最大可见性的未被覆盖成员
            CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtilKt.findMemberWithMaxVisibility(fromSuperQueue);
            // 提取可以在两个方向上覆盖的成员
            Collection<CallableMemberDescriptor> overridables =
                    extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue, strategy);
            // 创建并绑定假覆盖
            createAndBindFakeOverride(overridables, current, strategy);
        }
    }


    @NotNull
    private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
            @NotNull CallableMemberDescriptor overrider,
            @NotNull Queue<CallableMemberDescriptor> extractFrom,
            @NotNull OverridingStrategy strategy
    ) {
        return extractMembersOverridableInBothWays(overrider, extractFrom,
                // ID
                descriptor -> descriptor,
                descriptor -> {
                    strategy.inheritanceConflict(overrider, descriptor);
                    return Unit.INSTANCE;
                });
    }

    @NotNull
    private static Modality determineModalityForFakeOverride(
            @NotNull Collection<CallableMemberDescriptor> descriptors,
            @NotNull ClassDescriptor current
    ) {
        // Optimization: avoid creating hash sets in frequent cases when modality can be computed trivially
        boolean hasOpen = false;
        boolean hasAbstract = false;
        for (CallableMemberDescriptor descriptor : descriptors) {
            switch (descriptor.getModality()) {
                case FINAL:
                    return Modality.FINAL;
                case SEALED:
                    throw new IllegalStateException("Member cannot have SEALED modality: " + descriptor);
                case OPEN:
                    hasOpen = true;
                    break;
                case ABSTRACT:
                    hasAbstract = true;
                    break;
            }
        }

        // Fake overrides of abstract members in non-abstract expected classes should not be abstract, because otherwise it would be
        // impossible to inherit a non-expected class from that expected class in common code.
        // We're making their modality that of the containing class, because this is the least confusing behavior for the users.
        // However, it may cause problems if we reuse resolution results of common code when compiling platform code
        boolean transformAbstractToClassModality =
                current.isExpect() && (Modality.ABSTRACT != current.getModality() && Modality.SEALED != current.getModality());

        if (hasOpen && !hasAbstract) {
            return Modality.OPEN;
        }
        if (!hasOpen && hasAbstract) {
            return transformAbstractToClassModality ? current.getModality() : Modality.ABSTRACT;
        }

        Set<CallableMemberDescriptor> allOverriddenDeclarations = new HashSet<>();
        for (CallableMemberDescriptor descriptor : descriptors) {
            allOverriddenDeclarations.addAll(getOverriddenDeclarations(descriptor));
        }
        return getMinimalModality(filterOutOverridden(allOverriddenDeclarations), transformAbstractToClassModality, current.getModality());
    }

    @NotNull
    private static Modality getMinimalModality(
            @NotNull Collection<CallableMemberDescriptor> descriptors,
            boolean transformAbstractToClassModality,
            @NotNull Modality classModality
    ) {
        Modality result = Modality.ABSTRACT;
        for (CallableMemberDescriptor descriptor : descriptors) {
            Modality effectiveModality =
                    transformAbstractToClassModality && Modality.ABSTRACT == descriptor.getModality()
                            ? classModality
                            : descriptor.getModality();
            if (0 > effectiveModality.compareTo(result)) {
                result = effectiveModality;
            }
        }
        return result;
    }

    @NotNull
    public static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
            @NotNull ClassDescriptor current,
            @NotNull Collection<CallableMemberDescriptor> toFilter
    ) {
        return CollectionsKt.filter(toFilter, descriptor -> {
            //nested class could capture private member, so check for private visibility added
            return !DescriptorVisibilities.isPrivate(descriptor.getVisibility()) &&
                    DescriptorVisibilities.isVisibleIgnoringReceiver(descriptor, current, false);
        });
    }


    private static void createAndBindFakeOverride(
            @NotNull Collection<CallableMemberDescriptor> overridables,
            @NotNull ClassDescriptor current,
            @NotNull OverridingStrategy strategy
    ) {
        Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
        boolean allInvisible = visibleOverridables.isEmpty();
        Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;

        Modality modality = determineModalityForFakeOverride(effectiveOverridden, current);
//        DescriptorVisibility visibility = allInvisible ? DescriptorVisibilities.INVISIBLE_FAKE : DescriptorVisibilities.INHERITED;
        DescriptorVisibility visibility = allInvisible ? DescriptorVisibilities.INVISIBLE_FAKE : DescriptorVisibilities.INHERITED;

        // FIXME doesn't work as expected for flexible types: should create a refined signature.
        // Current algorithm produces bad results in presence of annotated Java signatures such as:
        //      J: foo(s: String!): String -- @NotNull String foo(String s);
        //      K: foo(s: String): String?
        //  --> 'foo(s: String!): String' as an inherited signature with most specific return type.
        // This is bad because it can be overridden by 'foo(s: String?): String', which is not override-equivalent with K::foo above.
        // Should be 'foo(s: String): String'.
        CallableMemberDescriptor mostSpecific =
                selectMostSpecificMember(effectiveOverridden,
                        descriptor -> descriptor);
        CallableMemberDescriptor fakeOverride =
                mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
        strategy.setOverriddenDescriptors(fakeOverride, effectiveOverridden);
        assert !fakeOverride.getOverriddenDescriptors().isEmpty()
                : "Overridden descriptors should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
        strategy.addFakeOverride(fakeOverride);
    }

    /**
     * @return overridden real descriptors (not fake overrides). Note that most usages of this method should be followed by calling
     * {@link #filterOutOverridden(Set)}, because some of the declarations can override the other.
     */
    @NotNull
    public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
        Set<CallableMemberDescriptor> result = new LinkedHashSet<>();
        collectOverriddenDeclarations(descriptor, result);
        return result;
    }

    private static void collectOverriddenDeclarations(
            @NotNull CallableMemberDescriptor descriptor,
            @NotNull Set<CallableMemberDescriptor> result
    ) {
        if (descriptor.getKind().isReal()) {
            result.add(descriptor);
        } else {
            if (descriptor.getOverriddenDescriptors().isEmpty()) {
                throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
            }
            for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
                collectOverriddenDeclarations(overridden, result);
            }
        }
    }

    /**
     * @return whether f overrides g
     */
    public static <D extends CallableDescriptor> boolean overrides(
            @NotNull D f,
            @NotNull D g,
            boolean allowDeclarationCopies,
            boolean distinguishExpectsAndNonExpects
    ) {
        // In a multi-module project different "copies" of the same class may be present in different libraries,
        // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).

        // This first check cover the case of duplicate classes in different modules:
        // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions,
        // we'll be getting sets of members that do not override each other, but are structurally equivalent.
        // As other code relies on no equal descriptors passed here, we guard against f == g, but this may not be necessary
        // Note that this is needed for the usage of this function in the IDE code
        if (!f.equals(g)
                && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
                f.getOriginal(),
                g.getOriginal(),
                allowDeclarationCopies,
                distinguishExpectsAndNonExpects
        )
        ) {
            return true;
        }

        CallableDescriptor originalG = g.getOriginal();
        for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) {
            if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
                    originalG,
                    overriddenFunction,
                    allowDeclarationCopies,
                    distinguishExpectsAndNonExpects
            )) {
                return true;
            }
        }
        return false;
    }

    @NotNull
    public static <D> Set<D> filterOverrides(
            @NotNull Set<D> candidateSet,
            boolean allowDescriptorCopies,
            @Nullable Function0<?> cancellationCallback,
            @NotNull Function2<? super D, ? super D, Pair<CallableDescriptor, CallableDescriptor>> transformFirst
    ) {
        if (1 >= candidateSet.size()) return candidateSet;

        Set<D> result = new LinkedHashSet<>();
        outerLoop:
        for (D meD : candidateSet) {
            if (null != cancellationCallback) {
                cancellationCallback.invoke();
            }
            for (Iterator<D> iterator = result.iterator(); iterator.hasNext(); ) {
                D otherD = iterator.next();
                Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD);
                CallableDescriptor me = meAndOther.component1();
                CallableDescriptor other = meAndOther.component2();
                if (overrides(me, other, allowDescriptorCopies, true)) {
                    iterator.remove();
                } else if (overrides(other, me, allowDescriptorCopies, true)) {
                    continue outerLoop;
                }
            }
            result.add(meD);
        }

        assert !result.isEmpty() : "All candidates filtered out from " + candidateSet;

        return result;
    }

    private static boolean isVisibilityMoreSpecific(
            @NotNull DeclarationDescriptorWithVisibility a,
            @NotNull DeclarationDescriptorWithVisibility b
    ) {
        Integer result = DescriptorVisibilities.compare(a.getVisibility(), b.getVisibility());
        return null == result || 0 <= result;
    }

    private static boolean isReturnTypeMoreSpecific(
            @NotNull CallableDescriptor a,
            @NotNull CangJieType aReturnType,
            @NotNull CallableDescriptor b,
            @NotNull CangJieType bReturnType,
            @NotNull TypeCheckerState typeCheckerState
    ) {
        return AbstractTypeChecker.INSTANCE.isSubtypeOf(typeCheckerState, aReturnType.unwrap(), bReturnType.unwrap());
    }

    public static boolean isMoreSpecific(@NotNull CallableDescriptor a, @NotNull CallableDescriptor b) {
        CangJieType aReturnType = a.getReturnType();
        CangJieType bReturnType = b.getReturnType();

        assert null != aReturnType : "Return type of " + a + " is null";
        assert null != bReturnType : "Return type of " + b + " is null";

        if (!isVisibilityMoreSpecific(a, b)) return false;


        TypeCheckerState checkerState =
                DEFAULT.createTypeCheckerState(a.getTypeParameters(), b.getTypeParameters());

        if (a instanceof FunctionDescriptor) {
            assert b instanceof FunctionDescriptor : "b is " + b.getClass();

            return isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType, checkerState);
        }
        if (a instanceof VariableDescriptor pa) {
            assert b instanceof VariableDescriptor : "b is " + b.getClass();

            VariableDescriptor pb = (VariableDescriptor) b;

//            if (!isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false;

            if (pa.isVar() && pb.isVar()) {
                // TODO(dsavvinov): using DEFAULT here looks suspicious
                return AbstractTypeChecker.INSTANCE.equalTypes(checkerState, aReturnType.unwrap(), bReturnType.unwrap());
            } else {
                // both vals or var vs val: val can't be more specific then var
                return !(!pa.isVar() && pb.isVar()) && isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType, checkerState);
            }
        }
        throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
    }

    private static boolean isMoreSpecificThenAllOf(@NotNull CallableDescriptor candidate, @NotNull Collection<CallableDescriptor> descriptors) {
        // NB subtyping relation in CangJie is not transitive in presence of flexible types:
        //  String? <: String! <: String, but not String? <: String
        for (CallableDescriptor descriptor : descriptors) {
            if (!isMoreSpecific(candidate, descriptor)) {
                return false;
            }
        }
        return true;
    }

    //    private static bool isAccessorMoreSpecific(@Nullable PropertyAccessorDescriptor a, @Nullable PropertyAccessorDescriptor b) {
//        if (a == null || b == null) return true;
//        return isVisibilityMoreSpecific(a, b);
//    }
    @NotNull
    public static <H> H selectMostSpecificMember(
            @NotNull Collection<H> overridables,
            @NotNull Function1<H, CallableDescriptor> descriptorByHandle
    ) {
        assert !overridables.isEmpty() : "Should have at least one overridable descriptor";

        if (1 == overridables.size()) {
            return CollectionsKt.first(overridables);
        }

        Collection<H> candidates = new ArrayList<>(2);
        List<CallableDescriptor> callableMemberDescriptors = CollectionsKt.map(overridables, descriptorByHandle);

        H transitivelyMostSpecific = CollectionsKt.first(overridables);
        CallableDescriptor transitivelyMostSpecificDescriptor = descriptorByHandle.invoke(transitivelyMostSpecific);

        for (H overridable : overridables) {
            CallableDescriptor descriptor = descriptorByHandle.invoke(overridable);
            if (isMoreSpecificThenAllOf(descriptor, callableMemberDescriptors)) {
                candidates.add(overridable);
            }
            if (isMoreSpecific(descriptor, transitivelyMostSpecificDescriptor)
                    && !isMoreSpecific(transitivelyMostSpecificDescriptor, descriptor)) {
                transitivelyMostSpecific = overridable;
            }
        }

        if (candidates.isEmpty()) {
            return transitivelyMostSpecific;
        } else if (1 == candidates.size()) {
            return CollectionsKt.first(candidates);
        }

        H firstNonFlexible = null;
        for (H candidate : candidates) {
            //noinspection ConstantConditions
            if (!FlexibleTypesKt.isFlexible(descriptorByHandle.invoke(candidate).getReturnType())) {
                firstNonFlexible = candidate;
                break;
            }
        }
        if (null != firstNonFlexible) {
            return firstNonFlexible;
        }

        return CollectionsKt.first(candidates);
    }

    /**
     * @param <H> is something that handles CallableDescriptor inside
     * @return
     */
    @NotNull
    public static <H> Collection<H> extractMembersOverridableInBothWays(
            @NotNull H overrider,
            @NotNull /*@Mutable*/ Collection<H> extractFrom,
            @NotNull Function1<H, CallableDescriptor> descriptorByHandle,
            @NotNull Function1<H, Unit> onConflict
    ) {
        Collection<H> overridable = new ArrayList<>();
        overridable.add(overrider);
        CallableDescriptor overriderDescriptor = descriptorByHandle.invoke(overrider);
        for (Iterator<H> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
            H candidate = iterator.next();
            CallableDescriptor candidateDescriptor = descriptorByHandle.invoke(candidate);
            if (overrider == candidate) {
                iterator.remove();
                continue;
            }

            OverrideCompatibilityInfo.Result finalResult = getBothWaysOverridability(overriderDescriptor, candidateDescriptor);

            if (OVERRIDABLE == finalResult) {
                overridable.add(candidate);
                iterator.remove();
            } else if (CONFLICT == finalResult) {
                onConflict.invoke(candidate);
                iterator.remove();
            }
        }
        return overridable;
    }

    private static List<CangJieType> compiledValueParameters(CallableDescriptor callableDescriptor) {
//        ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
        List<CangJieType> parameters = new ArrayList<>();
//        if (receiverParameter != null) {
//            parameters.add(receiverParameter.getType());
//        }
        for (ValueParameterDescriptor valueParameterDescriptor : callableDescriptor.getValueParameters()) {
            parameters.add(valueParameterDescriptor.getType());
        }
        return parameters;
    }

    /**
     * 检查两个描述符之间的基本覆盖（重写）兼容性问题
     * 此方法主要用于识别在 attempting to override a member in a superclass or interface 时是否存在基本的不兼容问题
     * 它不考虑更复杂的覆盖规则或条件，只提供初步的兼容性检查
     *
     * @param superDescriptor 超类或接口的描述符
     * @param subDescriptor   子类的描述符
     * @return 如果存在基本的覆盖兼容性问题，则返回问题的信息；否则返回 null
     */
    @Nullable
    public static OverrideCompatibilityInfo getBasicOverridabilityProblem(
            @NotNull CallableDescriptor superDescriptor,
            @NotNull CallableDescriptor subDescriptor
    ) {
        //        检查静态覆盖
        if (superDescriptor.isStatic() != subDescriptor.isStatic()) {
            if (subDescriptor.isStatic()) {

                return OverrideCompatibilityInfo.staticConflict(CangJieDiagnosisBundle.message("CONFLICTING_STATIC_BY_STATIC_TO_NON_STATIC", subDescriptor.getName()));
            }
            return OverrideCompatibilityInfo.staticConflict(CangJieDiagnosisBundle.message("CONFLICTING_STATIC_BY_NON_STATIC_TO_STATIC", subDescriptor.getName()));
        }
        // 检查是否涉及枚举类描述符，因为枚举成员不能覆盖非枚举成员
        if (subDescriptor instanceof EnumClassCallableDescriptor || superDescriptor instanceof EnumClassCallableDescriptor) {
            return OverrideCompatibilityInfo.incompatible("Enum member cannot override non-enum member");
        }

        // 检查成员种类是否匹配，即函数描述符只能被函数描述符覆盖，变量描述符只能被变量描述符覆盖
        if (superDescriptor instanceof FunctionDescriptor && !(subDescriptor instanceof FunctionDescriptor) ||
                superDescriptor instanceof VariableDescriptor && !(subDescriptor instanceof VariableDescriptor)) {
            return OverrideCompatibilityInfo.incompatible("Member kind mismatch");
        }

        // 确保超类描述符是可检查覆盖性的类型
        if (!(superDescriptor instanceof FunctionDescriptor) && !(superDescriptor instanceof VariableDescriptor)) {
            throw new IllegalArgumentException("This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor);
        }

        // 检查成员名称是否相同，名称不相同不能覆盖
        // TODO: check outside of this method
        if (!superDescriptor.getName().equals(subDescriptor.getName())) {
            return OverrideCompatibilityInfo.incompatible("Name mismatch");
        }

        // 进一步检查接收者和参数数量的兼容性
        return checkReceiverAndParameterCount(superDescriptor, subDescriptor);
    }

    /**
     * 检查接收器和参数数量的兼容性
     * <p>
     * 此方法用于检查超类和子类的 CallableDescriptor 对象的接收器和参数数量是否兼容。
     * 如果接收器存在性不匹配或参数数量不匹配，则返回一个 OverrideCompatibilityInfo 对象，表明存在兼容性问题。
     *
     * @param superDescriptor 超类的 CallableDescriptor 对象
     * @param subDescriptor   子类的 CallableDescriptor 对象
     * @return 如果存在兼容性问题，返回相应的 OverrideCompatibilityInfo 对象；如果没有问题，返回 null
     */
    @Nullable
    private static OverrideCompatibilityInfo checkReceiverAndParameterCount(
            CallableDescriptor superDescriptor,
            CallableDescriptor subDescriptor
    ) {
        //        TODO 如果使用扩展接收器，那么这里就要注释掉
        // 检查接收器是否存在，如果存在性不匹配，则返回一个 OverrideCompatibilityInfo 对象
//        if ((superDescriptor.getExtensionReceiverParameter() == null)!= (subDescriptor.getExtensionReceiverParameter() == null)) {
//            return OverrideCompatibilityInfo.incompatible("Receiver presence mismatch");
//        }

        // 检查参数数量是否匹配，如果不匹配，则返回一个 OverrideCompatibilityInfo 对象
        if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
            return OverrideCompatibilityInfo.incompatible("Value parameter number mismatch");
        }

        // 如果没有发现兼容性问题，则返回 null
        return null;
    }


    /**
     * 检查两种类型是否等价
     * 此方法用于比较在超类和子类中使用的两种类型是否等价，以支持类型检查和推断
     * 它首先检查两种类型是否都为错误类型，如果是，则认为它们等价
     * 如果两种类型都不是错误类型，则委托给AbstractTypeChecker进行类型等价性比较
     *
     * @param typeInSuper      超类中的类型
     * @param typeInSub        子类中的类型
     * @param typeCheckerState 类型检查器的状态，用于跟踪类型检查过程中的信息
     * @return 如果两种类型等价则返回true，否则返回false
     */
    private static boolean areTypesEquivalent(
            @NotNull CangJieType typeInSuper,
            @NotNull CangJieType typeInSub,
            @NotNull TypeCheckerState typeCheckerState
    ) {
        // 检查两种类型是否都为错误类型，如果是，则认为它们等价
        boolean bothErrors = CangJieTypeKt.isError(typeInSuper) && CangJieTypeKt.isError(typeInSub);
        if (bothErrors) return true;
        // 如果两种类型都不是错误类型，则委托给AbstractTypeChecker进行类型等价性比较
        return AbstractTypeChecker.INSTANCE.equalTypes(typeCheckerState, typeInSuper.unwrap(), typeInSub.unwrap());
    }

    // See JLS 8, 8.4.4 Generic Methods
    private static boolean areTypeParametersEquivalent(
            @NotNull TypeParameterDescriptor superTypeParameter,
            @NotNull TypeParameterDescriptor subTypeParameter,
            @NotNull TypeCheckerState typeCheckerState
    ) {
        List<CangJieType> superBounds = superTypeParameter.getUpperBounds();
        List<CangJieType> subBounds = new ArrayList<>(subTypeParameter.getUpperBounds());
        if (superBounds.size() != subBounds.size()) return false;

        outer:
        for (CangJieType superBound : superBounds) {
            ListIterator<CangJieType> it = subBounds.listIterator();
            while (it.hasNext()) {
                CangJieType subBound = it.next();
                if (areTypesEquivalent(superBound, subBound, typeCheckerState)) {
                    it.remove();
                    continue outer;
                }
            }
            return false;
        }

        return true;
    }

    @Nullable
    public static OverrideCompatibilityInfo.Result getBothWaysOverridability(
            CallableDescriptor overriderDescriptor,
            CallableDescriptor candidateDescriptor
    ) {
        OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidateDescriptor, overriderDescriptor, null).getResult();
        OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overriderDescriptor, candidateDescriptor, null).getResult();

        return OVERRIDABLE == result1 && OVERRIDABLE == result2
                ? OVERRIDABLE
                : ((CONFLICT == result1 || CONFLICT == result2) ? CONFLICT : INCOMPATIBLE);
    }

    /**
     * Given a set of descriptors, returns a set containing all the given descriptors except those which _are overridden_ by at least
     * one other descriptor from the original set.
     */
    @NotNull
    public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
//        boolean allowDescriptorCopies = !candidateSet.isEmpty() &&
//                DescriptorUtilsKt
//                        .isTypeRefinementEnabled(DescriptorUtilsKt.getModule(candidateSet.iterator().next()));
//
//        return filterOverrides(candidateSet, allowDescriptorCopies, null, new Function2<D, D, Pair<CallableDescriptor, CallableDescriptor>>() {
//            @Override
//            public Pair<CallableDescriptor, CallableDescriptor> invoke(D a, D b) {
//                return new Pair<CallableDescriptor, CallableDescriptor>(a, b);
//            }
//        });
        return candidateSet;
    }

    public static void resolveUnknownVisibilityForMember(
            @NotNull CallableMemberDescriptor memberDescriptor,
            @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility
    ) {
        for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
            if (descriptor.getVisibility() == DescriptorVisibilities.INHERITED) {
                resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility);
            }
        }

        if (memberDescriptor.getVisibility() != DescriptorVisibilities.INHERITED) {
            return;
        }

        DescriptorVisibility maxVisibility = computeVisibilityToInherit(memberDescriptor);
        DescriptorVisibility visibilityToInherit;
        if (null == maxVisibility) {
            if (null != cannotInferVisibility) {
                cannotInferVisibility.invoke(memberDescriptor);
            }
            visibilityToInherit = DescriptorVisibilities.PUBLIC;
        } else {
            visibilityToInherit = maxVisibility;
        }

        if (memberDescriptor instanceof PropertyDescriptorImpl) {
            ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
            for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
                // If we couldn't infer visibility for property, the diagnostic is already reported, no need to report it again on accessors
                resolveUnknownVisibilityForMember(accessor, null == maxVisibility ? null : cannotInferVisibility);
            }
        }/*else   if (memberDescriptor instanceof VariableDescriptorImpl) {
            ((VariableDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);

        } */ else if (memberDescriptor instanceof FunctionDescriptorImpl) {
            ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit);
        } else {
            assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
            PropertyAccessorDescriptorImpl propertyAccessorDescriptor = (PropertyAccessorDescriptorImpl) memberDescriptor;
            propertyAccessorDescriptor.setVisibility(visibilityToInherit);
            if (visibilityToInherit != propertyAccessorDescriptor.getCorrespondingProperty().getVisibility()) {
                propertyAccessorDescriptor.setDefault(false);
            }
        }
    }

    @Nullable
    public static DescriptorVisibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
        if (descriptors.isEmpty()) {
            return DescriptorVisibilities.DEFAULT_VISIBILITY;
        }
        DescriptorVisibility maxVisibility = null;
        for (CallableMemberDescriptor descriptor : descriptors) {
            DescriptorVisibility visibility = descriptor.getVisibility();
            assert visibility != DescriptorVisibilities.INHERITED : "Visibility should have been computed for " + descriptor;
            if (null == maxVisibility) {
                maxVisibility = visibility;
                continue;
            }
            Integer compareResult = DescriptorVisibilities.compare(visibility, maxVisibility);
            if (null == compareResult) {
                maxVisibility = null;
            } else if (0 < compareResult) {
                maxVisibility = visibility;
            }
        }
        if (null == maxVisibility) {
            return null;
        }
        for (CallableMemberDescriptor descriptor : descriptors) {
            Integer compareResult = DescriptorVisibilities.compare(maxVisibility, descriptor.getVisibility());
            if (null == compareResult || 0 > compareResult) {
                return null;
            }
        }
        return maxVisibility;
    }

    @Nullable
    private static DescriptorVisibility computeVisibilityToInherit(@NotNull CallableMemberDescriptor memberDescriptor) {
        Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors();
        DescriptorVisibility maxVisibility = findMaxVisibility(overriddenDescriptors);
        if (null == maxVisibility) {
            return null;
        }
        if (CallableMemberDescriptor.Kind.FAKE_OVERRIDE == memberDescriptor.getKind()) {
            for (CallableMemberDescriptor overridden : overriddenDescriptors) {
                // An implementation (a non-abstract overridden member) of a fake override should have the maximum possible visibility
                if (Modality.ABSTRACT != overridden.getModality() && !overridden.getVisibility().equals(maxVisibility)) {
                    return null;
                }
            }
            return maxVisibility;
        }
        return maxVisibility.normalize();
    }

//    /**
//     * 将sub 根据是否是扩展转换到super
//     * @param superDescriptor
//     * @param subDescriptor
//     * @return
//     */
//    @NotNull
//    static public CallableDescriptor conversion(
//            @NotNull CallableDescriptor superDescriptor,
//            @NotNull CallableDescriptor subDescriptor
//
//    ) {
//        List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
//        List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
//
//        if(subDescriptor.getExtensionReceiverParameter() != null &&  superTypeParameters.isEmpty()){
//            return subDescriptor;
//        }
//
//        return subDescriptor;
//    }

    /**
     * 提取并绑定成员的覆盖信息
     * 该方法用于处理当前类成员描述符与超类成员描述符之间的关系，根据可覆盖性将合适的超类成员绑定到当前类成员
     *
     * @param fromCurrent          当前类的成员描述符，用于检查与超类成员的覆盖关系
     * @param descriptorsFromSuper 超类的成员描述符集合，作为潜在被覆盖的成员
     * @param current              当前类的描述符，用于获取类上下文信息
     * @param strategy             覆盖策略接口，用于处理覆盖冲突等情况
     * @return 返回绑定后的成员描述符集合，包括了当前类成员覆盖的超类成员
     */
    private Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
            @NotNull CallableMemberDescriptor fromCurrent,
            @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
            @NotNull ClassDescriptor current,
            @NotNull OverridingStrategy strategy
    ) {
        // 初始化用于存储绑定后的成员描述符的集合
        Collection<CallableMemberDescriptor> bound = new ArrayList<>(descriptorsFromSuper.size());
        // 初始化用于存储被当前类成员覆盖的超类成员描述符的集合
        Collection<CallableMemberDescriptor> overridden = SmartSet.create();

        // 遍历超类成员描述符集合，检查每个成员是否被当前类成员覆盖
        for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
            // 检查超类成员是否可被当前类成员覆盖，以及覆盖的可见性
            OverrideCompatibilityInfo resultInfo = isOverridableBy(fromSupertype, fromCurrent, current);

            OverrideCompatibilityInfo.Result result = resultInfo.getResult();
            boolean isVisibleForOverride = isVisibleForOverride(fromCurrent, fromSupertype, false);

            // 根据覆盖检查结果，决定如何处理当前超类成员
            switch (result) {
                case OVERRIDABLE:
                    // 如果超类成员可被覆盖且可见，则将其添加到被覆盖成员集合中，并将其绑定到当前类成员
                    if (isVisibleForOverride) {
                        overridden.add(fromSupertype);
                    }
                    bound.add(fromSupertype);
                    break;
                case STATIC_CONFLICT:
                    // 如果存在静态覆盖冲突且可见，则调用覆盖策略处理冲突，并将其绑定到当前类成员
                    if (isVisibleForOverride) {
                        strategy.staticConflict(fromSupertype, fromCurrent, resultInfo.debugMessage);
                    }
                    bound.add(fromSupertype);
                    break;
                case CONFLICT:
                    // 如果存在覆盖冲突且可见，则调用覆盖策略处理冲突，并将其绑定到当前类成员
                    if (isVisibleForOverride) {
                        strategy.overrideConflict(fromSupertype, fromCurrent);
                    }
                    bound.add(fromSupertype);
                    break;
                case INCOMPATIBLE:
                    // 如果不可覆盖，则不进行任何操作
                    break;
            }
        }

        // 设置当前类成员所覆盖的超类成员描述符集合
        strategy.setOverriddenDescriptors(fromCurrent, overridden);

        // 返回绑定后的成员描述符集合
        return bound;
    }

    public <T extends CallableMemberDescriptor> void generateOverridesInFunctionGroup(
            @SuppressWarnings("UnusedParameters")
            @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
            @NotNull Collection<T> membersFromSupertypes,
            @NotNull Collection<T> membersFromCurrent,
            @NotNull ClassDescriptor current,
            @NotNull OverridingStrategy strategy
    ) {
        Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<>(membersFromSupertypes);

//        排除来自扩展的方法
        for (CallableMemberDescriptor member : notOverridden) {
            if (member instanceof FunctionDescriptor) {
                {
                    if (((FunctionDescriptor) member).getIsExtend()) {
                        membersFromCurrent.add((T) member);
                    }
                }
            }

        }


        for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
            Collection<CallableMemberDescriptor> bound =
                    extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, strategy);
            notOverridden.removeAll(bound);
        }

        createAndBindFakeOverrides(current, notOverridden, strategy);
    }

    @NotNull
    private TypeCheckerState createTypeCheckerState(
            @NotNull List<TypeParameterDescriptor> firstParameters,
            @NotNull List<TypeParameterDescriptor> secondParameters
    ) {
        assert firstParameters.size() == secondParameters.size() :
                "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters;

        if (firstParameters.isEmpty()) {
            return new OverridingUtilTypeSystemContext(
                    null, equalityAxioms, cangjieTypeRefiner, cangjieTypePreparator, customSubtype
            ).newTypeCheckerState(true, true);
        }

        Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<>();
        for (int i = 0; i < firstParameters.size(); i++) {
            matchingTypeConstructors.put(firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor());
        }

        return new OverridingUtilTypeSystemContext(
                matchingTypeConstructors, equalityAxioms, cangjieTypeRefiner, cangjieTypePreparator, customSubtype
        ).newTypeCheckerState(true, true);
    }

    /**
     * 检查一个描述符是否可以在不考虑外部条件的情况下覆盖另一个描述符
     * 此方法主要用于检查继承结构中方法的覆盖是否存在问题
     * 它通过比较超类和子类中的方法参数类型和返回类型来确定是否可以进行覆盖
     *
     * @param superDescriptor 超类的方法描述符
     * @param subDescriptor   子类的方法描述符
     * @param checkReturnType 是否检查返回类型
     * @return 返回一个OverrideCompatibilityInfo对象，包含覆盖是否成功或失败的原因
     */
    @NotNull
    public OverrideCompatibilityInfo isOverridableByWithoutExternalConditions(
            @NotNull CallableDescriptor superDescriptor,
            @NotNull CallableDescriptor subDescriptor,
            boolean checkReturnType
    ) {
        // 检查基本的覆盖问题，如抽象方法是否可以覆盖具体方法等
        OverrideCompatibilityInfo basicOverridability = getBasicOverridabilityProblem(superDescriptor, subDescriptor);
        if (null != basicOverridability) return basicOverridability;

        // 获取超类和子类方法的参数类型列表
        List<CangJieType> superValueParameters = compiledValueParameters(superDescriptor);
        List<CangJieType> subValueParameters = compiledValueParameters(subDescriptor);

        // 获取超类方法的类型参数列表
        List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();

        // 当成员为扩展时，有且只有一个类型参数，并且为扩展类型中的泛型时，需特殊处理
        List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParametersNotExtend();

        // 如果类型参数数量不匹配，则进一步检查参数类型是否兼容
        if (superTypeParameters.size() != subTypeParameters.size()) {
            for (int i = 0; i < superValueParameters.size(); ++i) {
                // TODO: compare erasure
                if (!CangJieTypeChecker.DEFAULT.equalTypes(superValueParameters.get(i), subValueParameters.get(i))) {
                    return OverrideCompatibilityInfo.incompatible("Type parameter number mismatch");
                }
            }
            return OverrideCompatibilityInfo.conflict("Type parameter number mismatch");
        }

        // 创建类型检查状态对象，用于后续的类型参数和值参数的比较
        TypeCheckerState typeCheckerState = createTypeCheckerState(superTypeParameters, subTypeParameters);

        // 检查类型参数是否等价
        for (int i = 0; i < superTypeParameters.size(); i++) {
            if (!areTypeParametersEquivalent(
                    superTypeParameters.get(i),
                    subTypeParameters.get(i),
                    typeCheckerState
            )) {
                return OverrideCompatibilityInfo.incompatible("Type parameter bounds mismatch");
            }
        }

        // 检查值参数类型是否等价
        for (int i = 0; i < superValueParameters.size(); i++) {
            if (!areTypesEquivalent(
                    superValueParameters.get(i),
                    subValueParameters.get(i),
                    typeCheckerState)
            ) {
                return OverrideCompatibilityInfo.incompatible("Value parameter type mismatch");
            }
        }


        // 检查返回类型是否兼容，如果需要检查返回类型的话
        if (checkReturnType) {
            CangJieType superReturnType = superDescriptor.getReturnType();
            CangJieType subReturnType = subDescriptor.getReturnType();

            if (null != superReturnType && null != subReturnType) {
                boolean bothErrors = CangJieTypeKt.isError(subReturnType) && CangJieTypeKt.isError(superReturnType);
                if (!bothErrors &&
                        !AbstractTypeChecker.INSTANCE.isSubtypeOf(
                                typeCheckerState,
                                subReturnType.unwrap(),
                                superReturnType.unwrap()
                        )
                ) {
                    return OverrideCompatibilityInfo.conflict("Return type mismatch");
                }
            }
        }


        // 如果所有检查都通过，则表示可以成功覆盖
        return OverrideCompatibilityInfo.success();
    }

    /**
     * 判断一个方法是否可以被重写。
     *
     * @param superDescriptor    父类的方法描述符。
     * @param subDescriptor      子类的方法描述符。
     * @param subClassDescriptor 子类的类描述符，可以为 null。
     * @param checkReturnType    是否检查返回类型。
     * @return 返回一个 {@link OverrideCompatibilityInfo} 对象，表示是否可以重写以及相关信息。
     * <p>
     * 方法执行流程如下：
     * 1. 首先调用 `isOverridableByWithoutExternalConditions` 方法进行基础的可重写性检查，
     * 判断是否可以在不考虑外部条件的情况下重写方法。
     * 2. 遍历所有外部的可重写性条件 {@link ExternalOverridabilityCondition}，根据其契约（`Contract`）：
     * - 如果契约是 `SUCCESS_ONLY`，则只在基本检查成功时执行。
     * - 如果契约是 `CONFLICTS_ONLY`，则跳过本次检查。
     * 3. 如果某个外部条件返回 `OVERRIDABLE`，则标记检查成功。
     * - 如果返回 `INCOMPATIBLE`，立即返回一个表示不兼容的结果。
     * - 如果返回 `UNKNOWN`，继续下一个条件检查。
     * 4. 如果基础检查失败且没有其他条件声明成功，直接返回基础检查的结果。
     * 5. 再次遍历所有外部条件，但这次仅运行契约为 `CONFLICTS_ONLY` 的条件，
     * 用于检测潜在的冲突：
     * - 如果条件返回 `INCOMPATIBLE`，返回不兼容结果。
     * - 如果条件返回 `OVERRIDABLE`，抛出异常，因为这违反了契约约定。
     * - 如果条件返回 `UNKNOWN`，继续下一个条件检查。
     * 6. 如果没有冲突且至少一个检查成功，则返回成功的结果。
     * @throws IllegalStateException 如果某个契约为 `CONFLICTS_ONLY` 的条件返回成功，违反契约。
     */
    @NotNull
    public OverrideCompatibilityInfo isOverridableBy(
            @NotNull CallableDescriptor superDescriptor,
            @NotNull CallableDescriptor subDescriptor,
            @Nullable ClassDescriptor subClassDescriptor,
            boolean checkReturnType
    ) {
        OverrideCompatibilityInfo basicResult = isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType);
        boolean wasSuccess = OVERRIDABLE == basicResult.getResult();

        for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
            // Do not run CONFLICTS_ONLY while there was no success
            if (ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY == externalCondition.getContract()) continue;
            if (wasSuccess && ExternalOverridabilityCondition.Contract.SUCCESS_ONLY == externalCondition.getContract())
                continue;

            ExternalOverridabilityCondition.Result result =
                    externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);

            switch (result) {
                case OVERRIDABLE:
                    wasSuccess = true;
                    break;
                case INCOMPATIBLE:
                    return OverrideCompatibilityInfo.incompatible("External condition");
                case UNKNOWN:
                    // do nothing
                    // go to the next external condition or default override check
            }
        }

        if (!wasSuccess) {
            return basicResult;
        }

        // Search for conflicts from external conditions
        for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
            // Run all conditions that was not run before (i.e. CONFLICTS_ONLY)
            if (ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY != externalCondition.getContract()) continue;

            ExternalOverridabilityCondition.Result result =
                    externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);
            switch (result) {
                case INCOMPATIBLE:
                    return OverrideCompatibilityInfo.incompatible("External condition");
                case OVERRIDABLE:
                    throw new IllegalStateException(
                            "Contract violation in " + externalCondition.getClass().getName() + " condition. It's not supposed to end with success");
                case UNKNOWN:
                    // do nothing
                    // go to the next external condition or default override check
            }
        }

        return OverrideCompatibilityInfo.success();
    }

    @NotNull
    public OverrideCompatibilityInfo isOverridableBy(
            @NotNull CallableDescriptor superDescriptor,
            @NotNull CallableDescriptor subDescriptor,
            @Nullable ClassDescriptor subClassDescriptor
    ) {
        return isOverridableBy(superDescriptor, subDescriptor, subClassDescriptor, false);
    }

    public static class OverrideCompatibilityInfo {
        private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(OVERRIDABLE, "SUCCESS");
        private final Result overridable;
        private final String debugMessage;

        public OverrideCompatibilityInfo(@NotNull Result success, @NotNull String debugMessage) {
            overridable = success;
            this.debugMessage = debugMessage;
        }

        @NotNull
        public static OverrideCompatibilityInfo success() {
            return SUCCESS;
        }

        @NotNull
        public static OverrideCompatibilityInfo incompatible(@NotNull String debugMessage) {
            return new OverrideCompatibilityInfo(INCOMPATIBLE, debugMessage);
        }

        @NotNull
        public static OverrideCompatibilityInfo staticConflict(@NotNull String debugMessage) {
            return new OverrideCompatibilityInfo(STATIC_CONFLICT, debugMessage);
        }

        @NotNull
        public static OverrideCompatibilityInfo conflict(@NotNull String debugMessage) {
            return new OverrideCompatibilityInfo(CONFLICT, debugMessage);
        }

        @NotNull
        public Result getResult() {
            return overridable;
        }

        @NotNull
        public String getDebugMessage() {
            return debugMessage;
        }

        @Override
        public String toString() {
            return overridable + ": " + debugMessage;
        }

        /**
         * 枚举类型Result用于表示不同结果状态
         * 这些结果状态可能在某些方法或逻辑判断中被使用，以决定程序的行为
         */
        public enum Result {
            /**
             * 可以被覆盖的结果状态
             * 这通常意味着当前结果可以被后续的某个操作或值覆盖
             */
            OVERRIDABLE,

            /**
             * 不兼容的结果状态
             * 这表示当前结果与预期或某些条件不兼容，可能需要特殊处理
             */
            INCOMPATIBLE,

            /**
             * 冲突的结果状态
             * 这通常意味着当前操作或值与已存在的状态存在冲突，需要解决
             */
            CONFLICT,
            /**
             * 静态冲突的结果状态
             */
            STATIC_CONFLICT
        }
    }
}
